﻿using System.Linq.PageList;
using Dyao.Book.Application.Abstractions;
using Dyao.Book.Contract;
using Dyao.Book.Core;
using Dyao.Book.Entity;
using Dyao.Book.Repository.Abstractions;
using Foundation.Caching;
using Foundation.Core;
using Foundation.IdCreate;
using Foundation.Uow;

namespace Dyao.Book.Application
{
    public class BookSourceSettingApplication : BaseApplication, IBookSourceSettingApplication
    {
        /// <summary>
        /// 书源仓储
        /// </summary>
        private readonly IBookSourceWarehouseRepository _warehouseRepository;
        /// <summary>
        /// 分布式缓存
        /// </summary>
        private readonly IDistributedMultiLevelCache _distributedMultiLevelCache;

        public BookSourceSettingApplication(IBookSourceWarehouseRepository warehouseRepository,
            IDistributedMultiLevelCache distributedMultiLevelCache)
        {
            _warehouseRepository = warehouseRepository;
            _distributedMultiLevelCache = distributedMultiLevelCache;
        }

        /// <inheritdoc cref="IBookSourceSettingApplication.GetPageListAsync"/>
        public async Task<IPageList<BookSourceSettingResultDto>> GetPageListAsync(IPageFilter<BookSourceSettingFilterDto> pageFilter, CancellationToken cancellationToken = default)
        {
            var result = new PageList<BookSourceSettingResultDto>();
            using (var unitOfWork = UnitOfWorkManager.Begin(isReadDb: true))
            {
                var pageList = await _warehouseRepository.GetPageListAsync(pageFilter, cancellationToken);
                if (pageList.Records == 0) return result;

                var resultList = ObjectMapper.Map<List<BookSourceWarehouseEntity>, List<BookSourceSettingResultDto>>(pageList.Data);

                return (PageList<BookSourceSettingResultDto>)pageList.ToMap(resultList);
            }
        }

        /// <inheritdoc cref="IBookSourceSettingApplication.AddAsync"/>
        public async Task<string> AddAsync(BookSourceSettingInfoDto setting, CancellationToken cancellationToken = default)
        {
            var idCreate = GetService<IIdCreater>();
            var code = await idCreate.CreateAsync(IdBusinessType.BookSourceRedisId, null, cancellationToken);
            var entity = ObjectMapper.Map<BookSourceSettingInfoDto, BookSourceWarehouseEntity>(setting);
            entity.ID = code.ToString();

            using (var unitOfWork = UnitOfWorkManager.Begin())
            {
                await _warehouseRepository.InsertAsync(entity, false, cancellationToken);
                await unitOfWork.SaveChangesAsync(cancellationToken);
                await unitOfWork.CompleteAsync(cancellationToken);
            }

            return "添加成功";
        }

        /// <inheritdoc cref="IBookSourceSettingApplication.ModifyAsync"/>
        public async Task<string> ModifyAsync(BookSourceSettingInfoDto setting, CancellationToken cancellationToken = default)
        {
            if (setting.Id.IsNullOrEmpty())
                throw new BusinessException("BookSourceSetting_Modify_Id", "书籍编号不能为空");

            using (var unitOfWork = UnitOfWorkManager.Begin())
            {
                var entity = await _warehouseRepository.GetByIdAsync(setting.Id, cancellationToken);
                if (entity == null)
                    throw new BusinessException("BookSourceSetting_Modify_SettingIsNull", "书源信息不存在");

                entity.SpiderRule = setting.SpiderRule;
                entity.Name = setting.Name;
                entity.Header = setting.Header;
                entity.SearchUrl = setting.SearchUrl;
                entity.Url = setting.Url;
                entity.UpdateUserId = CurrentUser.GetUserId().ToInt();
                entity.UpdateUserName = CurrentUser.UserName;
                entity.UpdateDateTime = DateTime.Now;

                await unitOfWork.SaveChangesAsync(cancellationToken);
                await unitOfWork.CompleteAsync(cancellationToken);
            }

            await _distributedMultiLevelCache.SetAsync(CacheConstants.SourceWarehouseCache, new List<BookSourceWarehouseDto>(), TimeSpan.FromSeconds(1)); // 清除缓存

            return "修改成功";
        }

        /// <inheritdoc cref="IBookSourceSettingApplication.DeleteAsync"/>
        public async Task<string> DeleteAsync(string id, CancellationToken cancellationToken = default)
        {
            if (id.IsNullOrEmpty())
                throw new BusinessException("BookSourceSetting_Delete_Id", "书源编号不能为空");

            var ids = id.SplitDefaultToList(); // 书籍编号

            using (var unitOfWork = UnitOfWorkManager.Begin(isTransactional: true))
            {
                var entities = await _warehouseRepository.GetListByIdsAsync(ids, b => new BookSourceWarehouseEntity { ID = b.ID, IsDel = b.IsDel }, cancellationToken);
                if (entities.IsNullOrEmpty())
                    throw new BusinessException("BookSourceSetting_Modify_SettingIsNull", "书源信息不存在");

                entities.ForEach(b => b.IsDel = true);

                await _warehouseRepository.BulkUpdateAsync(entities, b => new { b.IsDel }, cancellationToken);
                await unitOfWork.SaveChangesAsync(cancellationToken);
                await unitOfWork.CompleteAsync(cancellationToken);
            }
            return "删除成功";
        }

        /// <inheritdoc cref="IBookSourceSettingApplication.SwitchEnableAsync"/>
        public async Task<string> SwitchEnableAsync(string id, CancellationToken cancellationToken = default)
        {
            if (id.IsNullOrEmpty())
                throw new BusinessException("BookSourceSetting_Enable_Id", "书源编号不能为空");
            string msg = string.Empty;
            using (var unitOfWork = UnitOfWorkManager.Begin(isTransactional: true))
            {
                var entity = await _warehouseRepository.GetByIdAsync(id, cancellationToken);

                if (entity == null)
                    throw new BusinessException("BookSourceSetting_Enable_SettingsNull", "书源信息不存在");

                entity.Enabled = !entity.Enabled;
                entity.UpdateUserId = CurrentUser.GetUserId().ToInt();
                entity.UpdateUserName = CurrentUser.UserName;
                entity.UpdateDateTime = DateTime.Now;
                msg = entity.Enabled ? "启用成功" : "关闭成功";

                await unitOfWork.SaveChangesAsync(cancellationToken);
                await unitOfWork.CompleteAsync(cancellationToken);
            }

            return msg;
        }
    }
}
